package io.github.edwinliu.anynet;

import android.os.Environment;
import android.util.Log;
import android.util.Xml;

import org.xmlpull.v1.XmlPullParser;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.ServerSocket;
import java.net.Socket;

import de.robv.android.xposed.XposedBridge;

public class ServerThread extends Thread {
    static String TAG = "ServerThread";
    public ServerSocket tcpServerSocket;
    byte[] buffer = new byte[1000];
    Socket clientSocket;
    InputStream inputStream;
    int nbBytesRead = -1;
    boolean needToBeClosed = false;
    OutputStream oStream;
    byte[] output = null;
    String result;
    String strBuffer;

    boolean bFakeVpn=false;
    int netType=AnyNet.NETWORK_TYPE_NONE;

    public ServerThread() {
        XposedBridge.log("ServerThread constructor");
    }

    public void run() {
        XposedBridge.log("ServerThread : before open server");
        loadInitData();
        try {
            tcpServerSocket = new ServerSocket(43210);
        } catch (IOException e) {
            XposedBridge.log("error opening server socket "+e.toString());
            return;
        }

        while (!this.needToBeClosed) {
            XposedBridge.log("ServerThread : wait client");
            try {
                this.clientSocket = tcpServerSocket.accept();
                if (this.needToBeClosed) {
                    break;
                }
                XposedBridge.log("ServerThread : client accepted");
                this.inputStream = this.clientSocket.getInputStream();

                this.clientSocket.setSoTimeout(1000);
                this.nbBytesRead = this.inputStream.read(this.buffer);
                if (this.nbBytesRead > 0) {
                    this.nbBytesRead >>= 1;
                    this.strBuffer = new String(this.buffer, "UTF-8");
                    this.strBuffer = this.strBuffer.substring(0, this.nbBytesRead - 1);
                    String[] cmds = this.strBuffer.split(";");
                    if (cmds[0].compareToIgnoreCase("quit") == 0) {
                        this.needToBeClosed = true;
                        this.result = "OK:quit;";
                    } else if (cmds[0].startsWith("get:vpn")) {
                            this.result = "OK:"+bFakeVpn+";";
                    }else if (cmds[0].startsWith("set:vpn=")) {
                        boolean bFake=Boolean.parseBoolean(cmds[0].substring(8,cmds[0].length()-1));
                        bFakeVpn=bFake;
                        this.result = "OK:"+bFakeVpn+";";
                    }else if (cmds[0].startsWith("get:nettype")) {
                        this.result = "OK:"+netType+";";
                    }else if (cmds[0].startsWith("set:nettype=")) {
                        try {
                            int type=Integer.parseInt(cmds[0].substring(12,cmds[0].length()-1));
                            netType=type;
                            this.result = "OK:"+netType+";";
                        }catch (NumberFormatException e)
                        {
                            this.result = "KO:"+cmds[0]+";";
                            XposedBridge.log("set nettype "+e.toString());
                        }

                    }else {
                        XposedBridge.log("Unknow command");
                        this.result = "KO:unknow command;";
                    }

                    try {
                        this.output = this.result.getBytes("UTF-8");
                    } catch (UnsupportedEncodingException e3) {
                        XposedBridge.log("UnsupportedEncodingException");
                    }
                    try {
                        this.oStream = this.clientSocket.getOutputStream();
                        this.oStream.write(this.output);
                    } catch (IOException e4) {
                        XposedBridge.log("socketRead exception : " + e4.getMessage());
                        return;
                    }
                }
                this.clientSocket.close();
            } catch (Exception e) {
                XposedBridge.log("Exception "+e.toString());
            }
        }

        XposedBridge.log("Quit ServerThread");
        try {
            tcpServerSocket.close();
        } catch (IOException e) {
            XposedBridge.log("IOException close server socket");
        }

    }

    private  boolean loadInitData() {
        InputStream inStream;
        Log.d(TAG,"loadInitData ");
        try {
            File infile = new File(Environment.getDataDirectory(),
                    "data/io.github.edwinliu.anynet/shared_prefs/config.xml");
            inStream=new FileInputStream(infile);
        }catch (Exception e){
            XposedBridge.log("loadInitData "+e.toString());
            return false;
        }


        XmlPullParser parser = Xml.newPullParser();
        try {
            parser.setInput(inStream,"UTF-8");
            int eventType = parser.getEventType();

            while(eventType != XmlPullParser.END_DOCUMENT){
                switch (eventType){
                    case XmlPullParser.START_DOCUMENT:
                        break;
                    case XmlPullParser.START_TAG:
                        String name = parser.getAttributeValue(null,"name");
                        if(name==null)
                            break;
                        if(name.equalsIgnoreCase(ProviderUtils.KEY_NAME_VPN))
                        {
                            String value=parser.getAttributeValue(null,"value");
                            Log.d(TAG,"XML VPN "+value);
                            bFakeVpn=Boolean.parseBoolean(value);
                        }else  if(name.equalsIgnoreCase(ProviderUtils.KEY_NAME_NETTYPE))
                        {
                            String value=parser.getAttributeValue(null,"value");
                            Log.d(TAG,"XML NET TYPE "+value);
                            netType=Integer.parseInt(value);
                        }
                        break;
                    case XmlPullParser.END_TAG:
                        break;
                }
                eventType = parser.next();
            }
            inStream.close();

        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

}
